package com.example.lp.lpuicore.views.viewgroup;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * Author by lp,on 2021/1/19/019,9:57.
 * 仿京东搜索框流式布局
 * 自定义view/viewgroup流程
 */
public class FlowLayout extends ViewGroup {

    private static final String TAG = "FlowLayout";

    /*new*/
    public FlowLayout(Context context) {
        super(context);
        Log.i(TAG, "FlowLayout: ");
    }

    /*xml*/
    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.i(TAG, "FlowLayout: ");
    }

    /*切换主题*/
    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.i(TAG, "FlowLayout: ");
    }


    /*测量*/
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i(TAG, "onMeasure: ");
        //测量当前view大小
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
/*
        MeasureSpec 封装从父对象传递给孩子的布局要求。
        每个MeasureSpec表示宽度或高度的要求。
         MeasureSpec由尺寸和模式组成。 有三种模式：EXACTLY、AT_MOST、UNSPECIFIED
*/
        //记录宽高、如果当前的模式是 warp_content(UNSPECIFIED),适配组件内最大的宽高
        int witdh = 0;
        int height = 0;
        //记录每行的高度和宽度
        int lineWidth = 0;
        int lineheight = 0;
        //每次布局之前，清空缓存
        mAllViews.clear();
        mLineHeight.clear();  // 存放每一行的子view
        List<View> lineViews = new ArrayList<View>();
        //内部元素的个数
        int childCount = getChildCount();

        //循环获取元素的宽高
        for (int i = 0; i < childCount; i++) {
            //子元素
            View childAt = getChildAt(i);

            //测量子view的宽高
            measureChild(childAt, widthMeasureSpec, heightMeasureSpec);

            //获得layoutparms，获取子view的Margin
            MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();

            //子vierw占据的宽度
            int measuredWidth = childAt.getMeasuredWidth() + layoutParams.leftMargin
                    + layoutParams.rightMargin;
            //子vierw占据的高度
            int measuredHeight = childAt.getMeasuredHeight() + layoutParams.topMargin
                    + layoutParams.bottomMargin;

            //判断当前宽度之和是否超过 父view的宽度
            if (lineWidth + measuredWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {
                //获得行中的最大值为父view的宽度
                witdh = Math.max(witdh, lineWidth);
                //重置换行后的宽度
                lineWidth = measuredWidth;
                //累加高度
                height += lineheight;

                // 记录LineHeight
                mLineHeight.add(lineheight);
                // 记录当前行的Views
                mAllViews.add(lineViews);
                lineViews = new ArrayList<>();
                lineViews.add(childAt);
                //重置当前行最大高度
                lineheight = measuredHeight;

            }
            //不超过父view宽度的时候，更新当前行的高度
            else {
                //累加当前的子view宽度
                lineWidth += measuredWidth;
                //获得行中最大的高度
                lineheight = Math.max(lineheight, measuredHeight);
                lineViews.add(childAt);

            }
            //特殊情况，最后一个子view
            if (i == childCount - 1) {
                witdh = Math.max(lineWidth, witdh);
                height += lineheight;
                // 记录LineHeight
                mLineHeight.add(lineheight);
                // 记录当前行的Views
                mAllViews.add(lineViews);
            }
        }

        //重新决定宽高
        int measrueWith = modeWidth == MeasureSpec.EXACTLY ? sizeWidth : witdh + getPaddingLeft() + getPaddingRight();
        int measrueHeight = modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom();

        //设置宽高
        setMeasuredDimension(measrueWith, measrueHeight);

    }

    //存储所有子view
    private List<List<View>> mAllViews = new ArrayList<List<View>>();
    //每一行的高度
    private List<Integer> mLineHeight = new ArrayList<Integer>();

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.i(TAG, "onLayout: ");
        int lineHeight = 0;
        int left = getPaddingLeft();
        int top = getPaddingTop();
        //行数
        int lineNum = mAllViews.size();
        for (int i = 0; i < lineNum; i++) {
            //当前行的所有view
            List<View> lineViews = mAllViews.get(i);
            lineHeight = mLineHeight.get(i);
            //遍历行中所有view
            for (int j = 0; j < lineViews.size(); j++) {
                View view = lineViews.get(j);
                if (view.getVisibility() == GONE)
                    continue;

                MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + view.getMeasuredWidth();
                int bc = tc + view.getMeasuredHeight();

                //设置子view的位置
                view.layout(lc, tc, rc, bc);
                //重置left
                left += view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;

            }
            left = getPaddingLeft();
            top += lineHeight;
        }

    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attr) {
        Log.i(TAG, "generateLayoutParams: ");
        return new MarginLayoutParams(getContext(), attr);
    }
}
